﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bovril.Rodney.Core
{
    internal class ServiceClient : IServiceClient
    {
        #region Construction and Disposal
        internal ServiceClient()
        {
            serviceClientConfig_ = ServiceClientConfig.Load();

            globalServiceClient_ = new BFGlobalServiceReference.BFGlobalServiceClient();
            //ukExchangeServiceClient_ = new BFExchangeServiceReference.BFExchangeServiceClient();
            //australianExchangeServiceClient_ = new BFAusExchangeServiceReference.BFExchangeServiceClient();

            Login();
            EventHierarchy = new EventHierarchy(this);
        }

        public void Dispose()
        {
            try
            {
                Logout();

                globalServiceClient_.Close();
                //ukExchangeServiceClient_.Close();
                //australianExchangeServiceClient_.Close();
            }
            catch (Exception) { }// we can't emit an exception from a dispose call
        }
        #endregion Construction and Disposal

        #region Public Properties
        public IEventHierarchy EventHierarchy { get; private set; }
        #endregion

        #region Internal Methods
        internal IEvent[] GetActiveEvents()
        {
            BFGlobalServiceReference.GetEventTypesReq getEventTypesRequest = BetfairAPIGlobalRequestFactory.CreateGetEventTypesRequest(sessionToken_);
            BFGlobalServiceReference.GetEventTypesResp getEventTypesResponse = globalServiceClient_.getActiveEventTypes(getEventTypesRequest);
            BetfairAPIErrorProcessor.ProcessResponse(getEventTypesResponse);

            List<IEvent> rootEvents = new List<IEvent>();
            foreach (BFGlobalServiceReference.EventType eventType in getEventTypesResponse.eventTypeItems)
            {
                Event newEvent = new Event(this, eventType.id, eventType.name);
                rootEvents.Add(newEvent);
            }

            return rootEvents.ToArray();
        }

        internal IEvent[] GetChildEvents(Event evnt)
        {
            BFGlobalServiceReference.GetEventsReq getEventsRequest = BetfairAPIGlobalRequestFactory.CreateGetEventsRequest(sessionToken_, evnt.ID);
            BFGlobalServiceReference.GetEventsResp getEventsResponse = globalServiceClient_.getEvents(getEventsRequest);
            BetfairAPIErrorProcessor.ProcessResponse(getEventsResponse);

            List<IEvent> childEvents = new List<IEvent>();
            foreach (BFGlobalServiceReference.BFEvent bfEvent in getEventsResponse.eventItems)
            {
                Event childEvent = new Event(this, bfEvent.eventId, bfEvent.eventName, evnt/*, bfEvent.eventTypeId, bfEvent.menuLevel, bfEvent.orderIndex, bfEvent.startTime, bfEvent.timezone*/);
                childEvents.Add(childEvent);
            }

            return childEvents.ToArray();
        }

        internal ICouponLink[] GetCouponLinks(Event evnt)
        {
            BFGlobalServiceReference.GetEventsReq getEventsRequest = BetfairAPIGlobalRequestFactory.CreateGetEventsRequest(sessionToken_, evnt.ID);
            BFGlobalServiceReference.GetEventsResp getEventsResponse = globalServiceClient_.getEvents(getEventsRequest);
            BetfairAPIErrorProcessor.ProcessResponse(getEventsResponse);

            List<ICouponLink> couponLinks = new List<ICouponLink>();
            foreach (BFGlobalServiceReference.CouponLink bfCouponLink in getEventsResponse.couponLinks)
            {
                CouponLink couponLink = new CouponLink(bfCouponLink.couponId, bfCouponLink.couponName);
                couponLinks.Add(couponLink);
            }

            return couponLinks.ToArray();
        }

        internal IMarketSummary[] GetMarketSummaries(Event evnt)
        {
            BFGlobalServiceReference.GetEventsReq getEventsRequest = BetfairAPIGlobalRequestFactory.CreateGetEventsRequest(sessionToken_, evnt.ID);
            BFGlobalServiceReference.GetEventsResp getEventsResponse = globalServiceClient_.getEvents(getEventsRequest);
            BetfairAPIErrorProcessor.ProcessResponse(getEventsResponse);

            List<IMarketSummary> marketSummaries = new List<IMarketSummary>();
            foreach (BFGlobalServiceReference.MarketSummary bfMarketSummary in getEventsResponse.marketItems)
            {
                MarketSummary marketSummary = new MarketSummary(this, bfMarketSummary.marketId, bfMarketSummary.marketName, evnt);
                marketSummaries.Add(marketSummary);
            }

            return marketSummaries.ToArray();
        }
        #endregion

        #region Private Methods

        private void Login()
        {
            BFGlobalServiceReference.LoginReq loginRequest = BetfairAPIGlobalRequestFactory.CreateLoginRequest(serviceClientConfig_.Username, serviceClientConfig_.Password);
            BFGlobalServiceReference.LoginResp loginResp = globalServiceClient_.login(loginRequest);
            BetfairAPIErrorProcessor.ProcessResponse(loginResp);

            sessionToken_ = loginResp.header.sessionToken;
        }

        private void Logout()
        {
            BFGlobalServiceReference.LogoutReq logoutRequest = BetfairAPIGlobalRequestFactory.CreateLogoutRequest(sessionToken_);
            BFGlobalServiceReference.LogoutResp logoutResp = globalServiceClient_.logout(logoutRequest);
            BetfairAPIErrorProcessor.ProcessResponse(logoutResp);
        }

        #endregion Private Methods

        #region Private Data
        private ServiceClientConfig serviceClientConfig_;
        private BFGlobalServiceReference.BFGlobalServiceClient globalServiceClient_;
        //private BFExchangeServiceReference.BFExchangeServiceClient ukExchangeServiceClient_;
        //private BFAusExchangeServiceReference.BFExchangeServiceClient australianExchangeServiceClient_;

        private string sessionToken_;
        #endregion Private Data
    }
}
